package io.renren.modules.avanotes.component;

import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hankcs.hanlp.dictionary.CustomDictionary;
import io.renren.common.exception.BizCodeEnum;
import io.renren.common.exception.RRException;
import io.renren.config.BizConfig;
import io.renren.modules.avanotes.entity.LocalMarkdownNotesEntity;
import io.renren.modules.avanotes.service.LocalMarkdownNotesService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;

import javax.annotation.PostConstruct;
import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: xiaomi
 * @date: 2022/1/24
 * @description: 本地日志数据导入
 */
@Component
@Slf4j
public class LocalNotesBootstrapper {

    @Value("${notes.local.directory.path}")
    private String localDirectory;

    @Value("${dic.custom.path}")
    private String dicPath;

    @Value("${notes.import}")
    private Boolean needImport;

    @Autowired
    LocalMarkdownNotesService localMarkdownNotesService;

    /**
     * 关于生命周期；启动顺序？
     * 1.判断库内是否有数据
     * 2.为空，进行数据导入（由于做在系统启动时，所以这部分操作尽可能快）；
     * 3.导入时，通过 ik?使用hanlp 的索引全切分模式， 进行分词，存储在  redis 中。（使用定时任务进行轮询）
     * 4.
     */
    @PostConstruct
    public void init() {
        //1.导入数据
        putData();

        //2.加载新词到字典
        loadCustomVocabulary();
    }

    //region methods

    private void loadCustomVocabulary() {
        File file = new File(dicPath);
        if (!file.exists()) {
            log.info("本地新词不存在，不进行导入！");
            return;
            //throw new RRException(BizCodeEnum.FILE_NOT_FOUND.getMsg());
        }
        List<String> lines = FileUtil.readLines(file, Charset.defaultCharset());
        int num = 0;
        for (String line : lines) {
            CustomDictionary.add(line.trim(), BizConfig.COMPUTER_VOCABULARY_LABEL);
            num++;
        }
        log.info("一共加载了 {} 个自定义词汇", num);
    }

    private void putData() {
        if (!needImport) {
            log.info("needImport:false,不进行 notes 导入！");
            return;
        }
        //1.判断库内是否有数据- 放弃使用这种方式
//        int count = localMarkdownNotesService.count();
//        if (count > 0) {
//            log.info("库内已有数据，放弃导入...");
//            return;
//        }
        //2. 由于库为空，所以执行数据导入
        boolean isDir = FileUtil.isDirectory(localDirectory);
        if (!isDir) {
            throw new RRException(BizCodeEnum.DIRECTORY_NOT_FOUND.getMsg());
        }
        //3. 递归处理目录下的文件 Recurrence
        List<LocalMarkdownNotesEntity> list = new ArrayList<>();
        addEntities2ListRecursively(localDirectory, list);
        //4. 执行批量更新
//        localMarkdownNotesService.saveBatch(list);
        //执行更新 - 采用先判断 md5 再执行 replace into 的方式
        insertNotes(list);
    }

    private void insertNotes(List<LocalMarkdownNotesEntity> list) {
        for (LocalMarkdownNotesEntity entity : list) {
            int count = localMarkdownNotesService.count(new QueryWrapper<LocalMarkdownNotesEntity>().eq(LocalMarkdownNotesEntity.CN_MD5, entity.getMd5()));
            if (count == 0) {
                //如果没有相同内容的数据，执行 replace into
                localMarkdownNotesService.insertUpdate(entity);
            }
        }
    }

    private void addEntities2ListRecursively(String dirPath, List<LocalMarkdownNotesEntity> list) {
        //这个方法不会罗列目录！
        //List<String> fileNames = FileUtil.listFileNames(dirPath);
        File dir = new File(dirPath);
        String[] fileNames = dir.list();
        if (fileNames.length == 0) {
            //为空，放弃处理
            return;
        }
        for (String fileName : fileNames) {
            File file = new File(dirPath, fileName);
            if (file.isDirectory()) {
                //如果是目录，进行目录的处理方式
                addEntities2ListRecursively(file.getAbsolutePath(), list);
            } else {
                if (fileName.endsWith(BizConfig.MD_FILE_ACCEPTED_LABEL)) {
                    //位于 my-notes 之后的路径
                    String aPath = file.getAbsolutePath();
                    //+1 为了去掉路径符号
                    String rPath = aPath.substring(aPath.indexOf(localDirectory) + localDirectory.length() + 1);
                    //读取内容
                    String content = FileUtil.readString(file, Charset.defaultCharset());
                    //生成 md5
                    String md5 = DigestUtils.md5DigestAsHex(content.getBytes());
                    //处理 md 文件
                    LocalMarkdownNotesEntity entity = new LocalMarkdownNotesEntity(fileName, aPath, rPath, content, md5);
                    list.add(entity);
                }
            }
        }
    }
    //endregion

}
